/*
 DNN Content Builder - sourceforge.net/projects/dnncb
 Copyright (c) 2004-2008
 by Emerson Lopes (emersonlopes@gmail.com)

 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
 documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
 to permit persons to whom the Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all copies or substantial portions 
 of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Collections;
using System.Globalization;
using System.Resources;
using System.Web;
using System.Xml;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Portals;

namespace DNNContentBuilder
{
	/// <summary>
	/// The Commons class defines a set of small, general-purpose utility methods.
	/// </summary>
	public class Commons
	{
		#region Private Constructor
		/// <summary>
		/// Prevent direct instantiation
		/// </summary>
		private Commons() {}
		#endregion

		#region Static Methods
		
		/// <summary>
		///  Send a message to DNN Event Log
		/// </summary>
		/// <returns>Nothing</returns>

		public static void LogError(Exception e, string source) {
				DotNetNuke.Services.Log.EventLog.ExceptionLogController logController = new DotNetNuke.Services.Log.EventLog.ExceptionLogController();
			
				Exception err = new Exception(source + " " + e.Message + " " + e.StackTrace, e.InnerException);
				
				logController.AddLog(err, DotNetNuke.Services.Log.EventLog.ExceptionLogController.ExceptionLogType.GENERAL_EXCEPTION);
		}
		
		/// <summary>
		/// Gets the connection string for the first regular, non-primary-key
		/// field associated with the specified form definition.
		/// </summary>
		/// <returns>A connection string, or null if a valid FieldDefinitionInfo 
		/// cannot be determined from the form definition.</returns>

		public static string GetConnectionString(int formDefinitionId)
		{
			try {
				ArrayList fields = new FieldDefinitionController().GetByFormDefinition(formDefinitionId);

				foreach (FieldDefinitionInfo fdInfo in fields)
				{
					if (!fdInfo.IsPrimaryKey)
					{
						DataConnectionController dcController = new DataConnectionController();
						DataConnectionInfo dcInfo = dcController.GetItem(fdInfo.DataConnectionId);

						ConnectionStringController csController = new ConnectionStringController();
						ConnectionStringInfo csInfo = csController.GetItem(dcInfo.ConnectionStringId);

						return csInfo.ConnectionString;
					}
				}

				return null;
			}
			catch (Exception e) {
				return e.Message;
			}
		}
		
		// The following methods are necessary to deal with fckeditor encode
		public static string EncodeAngleBrackets(string text) { 
			text = text.Replace("\"", "&quot;");
			text = text.Replace("&apos;", "&amp;apos;");
			text = text.Replace("&nbsp;","&amp;nbsp;");

			// < & &lt;

			text = text.Replace("&lt;","&#38;&#60;"); // Special char "<" to temp html entity
			text = text.Replace("<","&lt;");
			text = text.Replace("&#38;&#60;", "&amp;lt;"); // Temp to &lt;

			// > & &gt;
			text = text.Replace("&gt;","&#38;&#62;"); // Special char ">" to temp html entity
			text = text.Replace(">","&gt;");
			text = text.Replace("&#38;&#62;", "&amp;gt;"); // Temp to &gt;
			
			return text;
		}

		public static string DecodeAngleBrackets(string text) {
			text = text.Replace("&quot;", "\"");

			// < & &lt;
			text = text.Replace("&amp;lt;","&#38;&#60;"); // Special char "<" to temp html entity
			text = text.Replace("&lt;","<");
			text = text.Replace("&#38;&#60;", "&lt;"); // Temp to &lt;

			// > & &gt;
			text = text.Replace("&amp;gt;","&#38;&#62;"); // Special char ">" to temp html entity
			text = text.Replace("&gt;",">");
			text = text.Replace("&#38;&#62;", "&gt;"); // Temp to &gt;
			
			text = text.Replace("&amp;apos;", "&apos;");
			text = text.Replace("&amp;&amp;", "&");
			text = text.Replace("&amp;nbsp;", "&nbsp;");
			
			return text;
		}
		
		public static string InsertChildNode(string node, string xml) {
				XmlDocument xd = new XmlDocument();
			
				xd.LoadXml(xml);
			
				XmlNode xmlNode = xd.FirstChild;
			
				xmlNode.InnerXml = node + xmlNode.InnerXml;
			
				xd.AppendChild(xmlNode);
				
				return xd.InnerXml;
		}

		public static string GetLocalizedString(string key, string resourceFileRoot, PortalSettings portalSettings)
		{
			try {
				return DotNetNuke.Services.Localization.Localization.GetString(key, resourceFileRoot, portalSettings, "pt-BR");
			}
			catch (Exception e) {
				return e.Message;
			}
		}

		public static string GetLocalizedString(string key, string fileNameRoot) 
		{
			try {
				string localString = DotNetNuke.Services.Localization.Localization.GetString(key, fileNameRoot);

				return localString != null ? localString : key.Replace("label_", "");
			}
			catch (Exception e) {
				return e.Message;
			}
		}

		public static string GetConnectionString(string connectionTitle) 
		{
			try {
				ConnectionStringController csController = new ConnectionStringController();

				return (csController.GetItemByTitle(connectionTitle)).ConnectionString;
			}
			catch (Exception e) {
				return e.Message;
			}
		}

		public static string GetURL(Int32 tabId, Int32 portalId, string GUID, string queryString) 
		{
			try {
	            DotNetNuke.Entities.Tabs.TabController tabController = new DotNetNuke.Entities.Tabs.TabController();

	            DotNetNuke.Entities.Tabs.TabInfo tabInfo = tabController.GetTab(tabId, portalId, true);
	
				// if querystring contains a GUID parameter, remove it
				if (queryString.IndexOf("GUID") > -1) {
					queryString = queryString.Remove(queryString.IndexOf("GUID="), queryString.IndexOf("GUID=") + 45);
					queryString = queryString.Replace("&&","");
				}
				
				string result = tabInfo.FullUrl + @"?GUID=" + GUID + @"&" + queryString;
				
				if (result.Substring(result.Length - 1) == "&") {
					result = result.Substring(0, result.Length - 1);
				}
			
				return result;
			}
			catch (Exception e) {
				return e.Message;
			}

		}
		#endregion
	}

	/// <summary>
	/// ContextUtil is an internal scoped class that defines a set of methods 
	/// which operate in the context of a PortalModule.
	/// </summary>
	internal class ContextUtil
	{
		#region Private Constructor
		/// <summary>
		/// Prevent direct instantiation
		/// </summary>
		private ContextUtil() {}
		#endregion

		#region Static Methods
		/// <summary>
		/// Gets the contents of the Type.xml file.
		/// </summary>
		/// <returns></returns>
		public static string GetTypeXml()
		{
			#region Hardcoded path to Type.xml
			const string path = @"DesktopModules\DNNContentBuilder\UserControls\FieldControls\XML\Type.xml";
			#endregion

			XmlDocument xdoc = new XmlDocument();

			xdoc.Load(HttpContext.Current.Server.MapPath(path));

			return xdoc.InnerXml;
		}


		public static PortalSettings GetPortalSettings(System.Web.UI.UserControl control)
		{
			PortalSettings result = null;
			PortalModuleBase host = GetPortalModule(control);

			if (host != null)
			{
				result = host.PortalSettings;
			}

			return result;
		}

		/// <summary>
		/// Get the module ID for a parent <see cref="DotNetNuke.Entities.Modules.PortalModuleBase"/>
		/// </summary>
		/// <param name="control"></param>
		/// <returns>The ModuleId, or Null.NullInteger if the naming container is not derived
		/// from <see cref="DotNetNuke.Entities.Modules.PortalModuleBase"/>.</returns>
		public static int GetModuleId(System.Web.UI.UserControl control)
		{
			int result = Null.NullInteger;
			PortalModuleBase host = GetPortalModule(control);

			if (host != null)
			{
				// Get the ModuleId
				result = host.ModuleId;
			}

			return result;
		}

		/// <summary>
		/// Get the portal ID for a parent <see cref="PortalModuleBase"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <returns>The portal ID, or Null.NullInteger if the naming container is
		/// not derived from <see cref="DotNetNuke.Entities.Modules.PortalModuleBase"/>.
		/// </returns>
		public static int GetPortalId(System.Web.UI.Control control)
		{
			int result = Null.NullInteger;
			PortalModuleBase host = GetPortalModule(control);

			if (host != null)
			{
				// Get the PortalId
				result = host.PortalId;
			}

			return result;
		}

		/// <summary>
		/// Gets the ID of the tab hosting the specified control.
		/// </summary>
		/// <param name="control"></param>
		/// <returns>The tab ID, or Null.NullInteger if the naming container 
		/// is not derived from <see cref="DotNetNuke.Entities.Modules.PortalModuleBase"/>.
		/// </returns>
		public static int GetTabId(System.Web.UI.Control control)
		{
			int result = Null.NullInteger;
			PortalModuleBase host = GetPortalModule(control);

			if (host != null)
			{
				// Get the TabId
				result = host.TabId;
			}

			return result;
		}

		/// <summary>
		/// Get the user ID for the logged on user in a parent <see cref="PortalModuleBase"/>.
		/// </summary>
		/// <param name="control"></param>
		/// <returns>The user ID, or Null.NullInteger if the naming container is
		/// not derived from <see cref="DotNetNuke.Entities.Modules.PortalModuleBase"/>.
		/// </returns>
		public static int GetUserId(System.Web.UI.Control control)
		{
			DotNetNuke.Entities.Users.UserInfo onlineUserInfo = DotNetNuke.Entities.Users.UserController.GetCurrentUserInfo();
			
			if (onlineUserInfo != null) {
				return onlineUserInfo.UserID;
			}
			
			//by convention if a user is not logged in, CMS must reject task creation (and content publishing).

			throw new Exception("@@INVALID: USER NOT LOGGED IN");
			                           
//			                           
//			int result = Null.NullInteger;
//			PortalModuleBase host = GetPortalModule(control);
//
//			if (host != null)
//			{
//				// Get the UserId
//				result = host.UserId;
//			}
//
//			return result;
		}

		/// <summary>
		/// Traverse the form hierarchy until we find a PortalModuleBase-derived
		/// naming container
		/// </summary>
		/// <param name="control"></param>
		/// <returns>A PortalModuleBase, or null if no suitable instance is found.</returns>
		private static PortalModuleBase GetPortalModule(System.Web.UI.Control control)
		{
			System.Web.UI.Control result = control;

			while (!(result is PortalModuleBase) && result.NamingContainer != null)
			{
				result = result.NamingContainer;
			}

			return (result is PortalModuleBase) ? (PortalModuleBase)result : null;
		}

		#region GetAttributeValue overloads
		/// <summary>
		/// This version expects a boolean attribute value.
		/// </summary>
		/// <param name="xmlDoc"></param>
		/// <param name="nodeName"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static bool GetAttributeValue(XmlDocument xmlDoc, string nodeName, bool defaultValue)
		{
			bool result = defaultValue;

			try
			{
				result = Boolean.Parse(GetAttributeValue(xmlDoc, nodeName, String.Empty));
			}
			catch (FormatException)
			{
				// Ignore the error
			}

			return result;
		}

		/// <summary>
		/// This version expects an Integer attribute value.
		/// </summary>
		/// <param name="xmlDoc"></param>
		/// <param name="nodeName"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static int GetAttributeValue(XmlDocument xmlDoc, string nodeName, int defaultValue)
		{
			int result = defaultValue;

			try
			{
				result = Int32.Parse(GetAttributeValue(xmlDoc, nodeName, String.Empty));
			}
			catch (FormatException)
			{
				// Ignore the error
			}

			return result;
		}

		/// <summary>
		/// This more general version expects a string version and can take null arguments.
		/// </summary>
		/// <param name="xmlDoc"></param>
		/// <param name="nodeName"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static string GetAttributeValue(XmlDocument xmlDoc, string nodeName, string defaultValue)
		{
			string result = defaultValue;

			if (xmlDoc != null && nodeName != null)
			{
				if (!nodeName.StartsWith("//"))
				{
					nodeName = "//" + nodeName;
				}

				XmlNode xmlNode = xmlDoc.SelectSingleNode(nodeName);

				if (xmlNode != null)
				{
					result = xmlNode.InnerText;
				}
			}

			return result;
		}
		#endregion

		#endregion
	}

	/// <summary>
	/// Locate and extract a literal string stored in an external resource.
	/// </summary>
	public class ResourceEngine
	{
		private static string ERR_RESOURCE_NOT_FOUND = "Specified resource {0} could not be located";

 		/// <summary>
		/// Prevent direct instantiation
		/// </summary>
		private ResourceEngine() {}

		/// <summary>
		/// Searches for the specified <see cref="System.String"/> in the specified resource
		/// in a case-sensitive manner.
		/// </summary>
		/// <param name="resourceId"></param>
		/// <returns></returns>
		public static string GetString(string resourceId)
		{
			// TODO: change this method to use a more appropriate message store
			ResourceManager manager = new ResourceManager(typeof(ResourceEngine));

		    string result;

		    try
			{
				result = manager.GetResourceSet(CultureInfo.CurrentCulture, true, true).GetString(resourceId, true);
			}
			catch (Exception ex)
			{
				throw new ApplicationException(String.Format(ERR_RESOURCE_NOT_FOUND, resourceId), ex);
			}

			return result;
		}
	}

	/// <summary>
	/// Utility class designed to display error messages to an user. Locate, 
	/// extract a literal string stored in an external resource and render it
	/// in the supplied container.
	/// </summary>
	public class ErrorProvider
	{
		/// <summary>
		/// Prevent direct instantiation
		/// </summary>
		private ErrorProvider() {}

		#region Constants
/*
		private const string resource = "~/DesktopModules/DNNContentBuilder/App_LocalResources/ResourceEngine";
*/
		#endregion

		public static void AddErrorMessage(System.Web.UI.WebControls.PlaceHolder container, string key, string resourceFile)
		{
			string errorMessage = Commons.GetLocalizedString(key, resourceFile);
			
			if (!container.Visible)
			{
				container.Visible = true;
			}

			container.Controls.Add(new System.Web.UI.LiteralControl(errorMessage));
		}
	}

	/// <summary>
	/// TODO: document
	/// </summary>

	[Serializable]
	public class FieldInfo 
	{
		#region Member Variables
		private string _Name;
		private string _ColumnProperties;
		private string _ColumnType;
		private int    _ControlTypeId;
		private int    _DataConnectionId;
		private string _ControlTypeName;
		#endregion
        
		#region Constructors
		public FieldInfo(string Name, string ColumnProperties, string ColumnType, int ControlTypeId, int DataConnectionId, string ControlTypeName)
		{
			_Name = Name;
			_ColumnProperties = ColumnProperties;
			_ColumnType = ColumnType;
			_ControlTypeId = ControlTypeId;
			_ControlTypeName = ControlTypeName;
			_DataConnectionId = DataConnectionId;
		}
		#endregion
        
		#region Properties
		public string name 
		{
			get { return _Name; }
			set { _Name = value; }
		}

		public string columnType
		{
			get { return _ColumnType; }
			set { _ColumnType = value; }
		}

		public string controlTypeName
		{
			get { return _ControlTypeName; }
			set { _ControlTypeName = value; }
		}

		public string columnProperties 
		{
			get { return _ColumnProperties; }
			set { _ColumnProperties = value; }
		}

		public int controlTypeId 
		{
			get { return _ControlTypeId; }
			set { _ControlTypeId = value; }
		}

		public int DataConnectionId 
		{
			get { return _DataConnectionId; }
			set { _DataConnectionId = value; }
		}

		#endregion
	}

	public class Pair 
	{
		#region Member Variables
		private string _name;
		private string _value;
		#endregion
        
		#region Constructors
		public Pair(string Name, string Value)
		{
			_name = Name;
			_value = Value;
		}
		#endregion
        
		#region Properties
		public string Name 
		{
			get { return _name; }
			set { _name = value; }
		}

		public string Value
		{
			get { return _value; }
			set { _value = value; }
		}
		#endregion
	}
}
